跨域的理解
跨域,顾名思义,即为请求了不同域的资源。
了解跨域这件事,我们先看看导致会存在跨域问题的根源:浏览器的同源策略
浏览器的同源策略又是什么鬼? 好像了解一点,但是又说不清楚。这次我们就来详细探索一下。
声明一下,本文是参考众多其他有关跨域文章结合自己技术认识所做的记录,请与
浏览器同源政策及其规避方法参考着看更加合适。
同源策略:(the same-origin policy)
MDN
维基百科:
In computing, the same-origin policy is an important concept in the web application security model. Under the policy, a web browser permits scripts contained in a first web page to access data in a second web page, but only if both web pages have the same origin. An origin is defined as a combination of URI scheme, host name, and port number. This policy prevents a malicious script on one page from obtaining access to sensitive data on another web page through that page's Document Object Model.
简单翻译一下:
在web应用安全模型中,同源策略是一个重要的概念。在该策略下,仅俩个页面有相同的源, web浏览器才允许包含在第一个页面中的脚本访问第二个web页面的数据。源被定义为 URI协议,主机名,端口号的组合。该策略阻止了一个页面的恶意脚本通过文档对象模型(DOM)获得其他的web页面的敏感数据.
那为什么会有同源策略呢,可以参考一下,CSRF这篇文章谈到CSRF这种情况。
那哪些数据会被限制呢?
敏感数据一般指的是浏览器中的Cookies, SessionStorage, LocalStorage, IndexedDB数据, CacheStorage, ApplicationCache...;
同源策略限制范围
阮一峰老师还对同源策略对于非同源,限制的行为做了归纳:
“
如果非同源,共有三种行为受到限制。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下面,我将详细介绍,如何规避上面三种限制。
”
以下对阮老师总结的方法进行测试
Cookies
浏览器允许通过设置document.domain共享 Cookie。
document.domain的写操作是有要求的。只能写入基础域名和当前域名,其他域名是无法写入的,所以domain这种方式只能在亲子域名之间共享cookies
// 由于还没有相关资源(三级域名资源,域名资源),没有做验证
iframe
页面1 localhost:8080的页面,包含一个页面2 (iframe = http://localhost:8081);
页面2中访问window.parent.document报跨源错误
在页面2中window.parent可以访问,但是在iframe中访问获取到的window.parent对象中属性缺少了有关DOM的部分,而直接在页面1中查看window对象,可以看到document属性对象,而使用夸源window.parent无法获取document属性对象
- 片段识别符(fragment identifier)
- window.name
- 跨文档通信API(Cross-document messaging)
片段识别符 fragment identifier
所以这种方式,无论是否夸源,父窗口可以通过更改子窗口的iframe的src中的hash值来传递数据给子窗口;
但是 在存在跨源的情况下,子窗口获取parent.location.href(可写不可读)读操作会报跨源错误,所以子窗口课件写入url的方式传递数据给父窗口。
片段识别符方式可以父传子,子传父。
window.name
document.getElementById('iframe').contentWindow.name
访问出错,所以无法跨域
window.postMessage
页面1 调用iframe的iframe.contentWindow.postMessage(data,"http://localhost:8081")
页面2 调用window的 window.parent.postMessage(data,'http://localhost:8080')
AJAX (最常见到的情况)
“
同源政策规定,AJAX请求只能发给同源的网址,否则就报错。
除了架设服务器代理(浏览器请求同源服务器,再由后者请求外部服务),有三种方法规避这个限制。
JSONP
WebSocket
CORS
”
JSONP
// 客户端(浏览器页面)
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');//需要指定回调函数名
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
//服务端
foo({
"ip": "8.8.8.8"
});
CORS
CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决方法。相比JSONP只能发GET请求,CORS允许任何类型的请求。
请参考 阮老师的跨域资源共享 CORS 详解
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。